package org.goj.practice.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.goj.common.entity.practice.Solution;
import org.goj.common.entity.practice.SourceCode;
import org.goj.common.entity.practice.SourceCodeUser;
import org.goj.practice.mapper.ProblemMapper;
import org.goj.practice.mapper.SolutionMapper;
import org.goj.practice.mapper.SourceCodeMapper;
import org.goj.practice.mapper.SourceCodeUserMapper;
import org.goj.practice.service.SolutionService;
import org.goj.practice.vo.SolutionContestVO;
import org.goj.practice.vo.SolutionSource;
import org.goj.practice.vo.StatusVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 程序运行结果记录 服务实现类
 * </p>
 *
 * @author CK
 * @since 2020-12-02
 */
@Service
public class SolutionServiceImpl extends ServiceImpl<SolutionMapper, Solution> implements SolutionService {

    @Resource
    private SourceCodeMapper sourceCodeMapper;

    @Resource
    private SourceCodeUserMapper sourceCodeUserMapper;

    @Resource
    private SolutionMapper solutionMapper;

    @Resource
    private ProblemMapper problemMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int submit(Solution solution, String source) {
        int solutionId = solutionMapper.saveGetId(solution);
        Assert.isTrue(solutionId == 1, "添加Solution失败");
        int f2 = sourceCodeMapper.insert(new SourceCode().setSolutionId(solution.getSolutionId())
                .setSource(source));
        Assert.isTrue(f2 == 1, "添加SourceCode失败");
        //似乎没什么用，但又懒得改了
        int f3 = sourceCodeUserMapper.insert(new SourceCodeUser().setSolutionId(solution.getSolutionId())
                .setSource(source));
        Assert.isTrue(f3 == 1, "添加SourceCodeUser失败");
        return solution.getSolutionId();
    }

    @Override
    public boolean updateSubmitProblem(Integer problemId) {
        int flag = problemMapper.updateSubmitProblem(problemId);
        Assert.isTrue(flag == 1, "更新Problem失败！");
        return true;
    }

    @Override
    public List<Solution> result(Integer solutionId) {
        return solutionMapper.result(solutionId);
    }

    @Override
    public List<Solution> result(Integer userId, Integer problemId, Integer contestId) {
        if (contestId == -1) {
            return solutionMapper.listResult(userId, problemId);
        } else {
            return solutionMapper.listContestResult(userId, problemId, contestId);
        }
    }

    @Override
    public Page<StatusVO> listStatus(Integer current, Integer size, Integer sort, String name, List<Integer> languageList, List<Integer> listResult) {
        Map<Integer, String> sortMap = Map.of(1, "memory", 2, "memory", 3, "time", 4, "time",
                5, "code_length", 6, "code_length", 7, "in_date", 8, "in_date");
        Page<StatusVO> page = new Page<>(current, size);
        QueryWrapper<StatusVO> queryWrapper = new QueryWrapper<>();
        queryWrapper
                //屏蔽竞赛状态查询
                //.eq("contest_id", 0).eq("num", -1)
                .in(ObjectUtil.isNotEmpty(languageList), "solution.language", languageList)
                .in(ObjectUtil.isNotEmpty(listResult), "solution.result", listResult)
                .and(StrUtil.isNotBlank(name), t -> t.like("user.nick", name).or().like("problem.title", name).or().like("solution.problem_id", name))
                .orderBy(sort != 0, (sort & 1) == 1, sortMap.get(sort));
        return solutionMapper.listStatus(page, queryWrapper);
    }

    @Override
    public SolutionSource solutionSourceById(Integer solutionId) {
        return solutionMapper.solutionSourceById(solutionId);
    }

    @Override
    public Page<SolutionContestVO> solutionContest(Integer current, Integer size, Integer contestId) {
        Page<SolutionContestVO> page = new Page<>(current, size);
        return solutionMapper.solutionContest(page, contestId);
    }

}
